Once a value has been found for an attribute (possibly by investigating a goal), it is useful to be able to explain why the attribute has that particular value.
A decision report is a recursive structure that contains a series of nodes, and explains the series of steps that led to an attribute having a particular value. A simple example follows.
The applicant is eligible for a driver's license because:
The applicant is over 16, because:
The applicant's age is 18, because:
Note:
The bold statements do not appear in a decision report, but are added here
for clarity
Each line above would be represented by a DecisionReportNode object.
Each DecisionReportNode may contain other DecisionReportNode objects as children. In the example above, 'The date of application' and 'The applicant's date of birth' are both children of the DecisionReportNode containing 'The applicant's age'.
Retrieving a decision report is simply a matter of calling Attribute.getDecisionReport() for the Attribute whose value needs to be explained. The task of displaying the decision report to the user is more difficult. However, the recursive nature of the DecisionReportNode objects makes it natural to write a recursive method to display the report.
The following code fragments follow on directly from the examples shown under Investigate a Goal, and use a recursive method to display a report for the global attribute 'a5' - click on the appropriate heading to view either the Java or the C# example:
Engine eng = Engine.INSTANCE;
Rulebase rb = eng.getRulebase(...);
Session sess = eng.createSession(rb);
EntityInstance globalEI = sess.getGlobalEntityInstance();
Entity globalEnt = globalEI.getEntity();
//set attribute values here
sess.think();
Attribute goalAttr = globalEnt.getAttribute("a5");
String goalValue = (String) goalAttr.getValue(globalEI);
System.out.println("The value of attribute a5 is " + goalValue);
System.out.println("This conclusion was reached because:");
// Now get the decision report so it can be displayed.
DecisionReportNode decisionRep = goalAttr.getDecisionReport(globalEI);
// Display the decision report, starting at an indentation
// level of 0. This is a recursive method.
displayDecisionReport(decisionRep, 0);
DisplayDecisionReport() is the method that displays each node of the decision report. For readability, each node of the decision report is indented under its parent node. The method is defined as follows:
private static void displayDecisionReport(DecisionReportNode node, int depth) {
for(int j = 0; j < depth; j++)
{
System.out.print(" ");
}
System.out.println(node.getAttributeText());
if(! node.isLeaf())
{
List children = node.getChildren();
for(int i = 0; i < children.size(); i++)
{
displayDecisionReport((DecisionReportNode) children.get(i), depth + 1);
}
}
}
Engine eng = Engine.INSTANCE;
Rulebase rb = eng.GetRulebase(...);
Session sess = eng.CreateSession(rb);
EntityInstance globalEI = sess.GetGlobalEntityInstance();
Entity globalEnt = globalEI.GetEntity();
//set attribute values here
sess.Think();
RBAttr goalAttr = globalEnt.GetAttribute("a5");
string goalValue = (string) goalAttr.GetValue(globalEI);
Console.Out.WriteLine("The value of attribute a5 is " + goalValue);
Console.Out.WriteLine("This conclusion was reached because:");
// Now get the decision report so it can be displayed.
// We pass in RELEVANT for the flags to retrieve all relevant
// nodes for the decision report.
DecisionReportNode decisionRep = goalAttr.GetDecisionReport(globalEI, DecisionReportFlag.RELEVANT);
// Display the decision report, starting at an indentation
// level of 0. This is a recursive method.
DisplayDecisionReport(decisionRep, 0);
DisplayDecisionReport() is the method that displays each node of the decision report. For readability, each node of the decision report is indented under its parent node. The method is defined as follows:
private static void DisplayDecisionReport(DecisionReportNode node, int depth)
{
for (int j = 0; j < depth; j++)
{
Console.Out.Write(" ");
}
Console.Out.WriteLine(node.GetAttributeText());
if (! node.IsLeaf())
{
List children = node.GetChildren();
foreach (DecisionReportNode child in children)
{
DisplayDecisionReport(child, depth + 1);
}
}
}